package com.parleys.helper;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteConstraintException;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.AsyncTask;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.parleys.R;
import com.parleys.activity.MyDownloadsActivity;
import com.parleys.domain.Channel;
import com.parleys.domain.Presentation;
import com.parleys.domain.PresentationAsset;
import com.parleys.domain.Space;
import com.parleys.service.intf.DBAdapter;
import com.parleys.service.intf.ParleysService;
import com.parleys.service.intf.PresentationAssetsService;

public class DownloadTask extends AsyncTask<Object, Object, Object> {

	private static final Integer IMAGES_TOTAL_PERCENTAGE = 10;
	private static final Integer MP3_TOTAL_PERCENTAGE = 89;
	private static final Integer DB_INSERTING_TOTAL_PRECENTAGE = 1;

	@Inject
	protected Provider<Context> contextProvider;

	@Inject
	private ParleysService parleysService;

	@Inject
	private PresentationAssetsService presentationAssetsService;

	@Inject
	private DBAdapter dbAdapter;

	private Space space;

	private Channel channel;

	private Presentation presentation;

	/** The total progress. A number between 0 and 100 */
	private Double totalProgress = 0d;

	private ProgressDialog progressDialog;

	private Context context;

	public DownloadTask(final Presentation presentation, final Channel channel, final Space space) {
		this.space = space;
		this.channel = channel;
		this.presentation = presentation;
	}

	public void start() {
		context = contextProvider.get();
		checkDownload();
	}

	private void notifyDownloadComplete() {
		final int notificationId = (int) (Math.random() * Integer.MAX_VALUE);
		NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
		Notification note = new Notification(R.drawable.iconbw, context.getString(R.string.download_completed), System
				.currentTimeMillis());
		note.flags |= Notification.FLAG_AUTO_CANCEL;
		PendingIntent intent = PendingIntent.getActivity(context, 0, new Intent(context, MyDownloadsActivity.class), 0);
		note.setLatestEventInfo(context, presentation.getName(), context.getString(R.string.download_completed), intent);
		notifManager.notify(notificationId, note);

	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		progressDialog = new ProgressDialog(context);
		progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		progressDialog.setMessage(context.getString(R.string.downloading));
		progressDialog.setCancelable(false);
		progressDialog.show();

		// TODO find a better way to set this
		context = context.getApplicationContext();
	}

	@Override
	protected Object doInBackground(Object... params) {
		startDownload();
		return null;
	}

	@Override
	protected void onPostExecute(Object result) {
		progressDialog.dismiss();
		notifyDownloadComplete();
	}

	@Override
	protected void onProgressUpdate(Object... values) {
		int totalInt = totalProgress.intValue();
		progressDialog.setProgress(totalInt);
		if (totalInt < IMAGES_TOTAL_PERCENTAGE) {
			progressDialog.setMessage(context.getString(R.string.downloading_images));
		} else if (totalInt < IMAGES_TOTAL_PERCENTAGE + MP3_TOTAL_PERCENTAGE) {
			progressDialog.setMessage(context.getString(R.string.downloading_mp3));
		} else if (totalInt < IMAGES_TOTAL_PERCENTAGE + MP3_TOTAL_PERCENTAGE + DB_INSERTING_TOTAL_PRECENTAGE) {
			progressDialog.setMessage(context.getString(R.string.inserting_presentation));
		} else {
			progressDialog.setMessage(context.getString(R.string.download_completed));
		}
	}

	private void checkDownload() {
		ConnectivityManager connectivityManager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		if (connectivityManager.getActiveNetworkInfo().getType() != ConnectivityManager.TYPE_WIFI) {
			new AlertDialog.Builder(context) //
					.setIcon(android.R.drawable.ic_dialog_alert)//
					.setTitle(context.getString(R.string.no_wifi_title))//
					.setMessage(context.getString(R.string.no_wifi_description))//
					.setPositiveButton(context.getString(R.string.no_wifi_ok), new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							execute();
						}
					}).setNegativeButton(context.getString(R.string.no_wifi_cancel), null)//
					.show();
		} else {
			execute();
		}
	}

	private void startDownload() {
		WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		WifiLock wifiLock = wifiManager.createWifiLock("lock");
		wifiLock.acquire();
		downloadImages();
		downloadMp3();
		insertPresentationInDB();
		wifiLock.release();
	}

	private void downloadImages() {
		List<PresentationAsset> images = new ArrayList<PresentationAsset>();
		for (PresentationAsset presentationAsset : parleysService.getPresentationAssets(presentation.getId(), true)) {
			if (ApplicationConstants.IMAGE.equals(presentationAsset.getType())) {
				images.add(presentationAsset);
			}
		}

		Double percentagePerImage = Double.valueOf(IMAGES_TOTAL_PERCENTAGE) / images.size();
		dbAdapter.openForWriting();
		for (PresentationAsset presentationAsset : images) {
			presentationAssetsService.getImage(channel.getAssetBaseURL(), "presentations", presentation.getId(),
					presentationAsset.getValue());
			totalProgress += percentagePerImage;

			publishProgress();
			try {
				dbAdapter.insertAssetForPresentationId(presentationAsset, presentation.getId());
			} catch (SQLiteConstraintException e) {
				// ignore, asset already exists
			}
		}
		dbAdapter.close();
	}

	private void downloadMp3() {
		presentationAssetsService.downloadMP3(channel.getMediaBaseURL(), presentation, new MP3DownloadCallback() {

			@Override
			public void updateProgress(Long totaldownloadedSize, Long totalSize) {
				totalProgress = Double.valueOf(totaldownloadedSize) / totalSize * MP3_TOTAL_PERCENTAGE
						+ IMAGES_TOTAL_PERCENTAGE;
				publishProgress();
				Thread.yield(); // give the gui some time to update
			}
		});

		totalProgress = Double.valueOf(MP3_TOTAL_PERCENTAGE + IMAGES_TOTAL_PERCENTAGE);
		publishProgress();
	}

	private void insertPresentationInDB() {
		dbAdapter.openForWriting();
		try {
			dbAdapter.insertSpace(space);
		} catch (SQLiteConstraintException e) {
			// ignore, space is already in db
		}
		try {
			dbAdapter.insertChannelForSpace(channel, space.getId());
		} catch (SQLiteConstraintException e) {
			// ignore, channel is already in db
		}
		try {
			dbAdapter.insertPresentationForChannelId(presentation, channel.getId());
		} catch (SQLiteConstraintException e) {
			// ignore, presentation is already in db
		}
		dbAdapter.close();
		totalProgress = 100d;
		publishProgress();
	}

}
